#ifndef AER_MESH_HPP_
#define AER_MESH_HPP_

#include "aerDefs.hpp"
#include "aerDrawable.hpp"
#include "device/aerVertexArray.hpp"
#include "device/aerDeviceBuffer.hpp"


namespace aer {


// TODO : rewrite it
class Mesh : public Drawable
{
  public:
    enum AttribLocation_t
    {
      POSITION = 0,
      TEXCOORD,
      NORMAL,
      TANGENT,
      BITANGENT,
      
      kNumAttribLocation
    };
    
    typedef int AttribLocation;
  
    enum Packing
    {
      SINGLE_BUFFER,
      INTERLEAVED,
      SEPARATED
    };
    
    struct Attrib 
    {
      const void *pData;
      U8          nComponent;
      
      Attrib() : pData(NULL), nComponent(0u) {}
    };
  
  
  private:
    VertexArray   m_vertexArray;
    DeviceBuffer  m_vbo[kNumAttribLocation];
    DeviceBuffer  m_ibo;

    Attrib        m_attribs[kNumAttribLocation];//    
    const void   *m_pIndices;//
    
    Packing       m_packing;//
    GLenum         m_primitiveType;//
    
    U32            m_numVertices;
    U32            m_numIndices;

  
  public:
    Mesh();
    ~Mesh();
    
    
    // TODO : custom Type
    void setAttrib(AttribLocation location, const float *data, 
                   U8 nComponent, U32 nElements);//
    
    // idem
    void setIndices(GLenum mode, const unsigned int *indices, U32 nElements);//
    
    void setPrimitiveType(GLenum mode) { m_primitiveType = mode; }
    
    
    void upload(DeviceBuffer::Usage usage, Packing packing=SINGLE_BUFFER);  
    
    
    // ====================
    // + Drawable methods +
    // ====================
    void draw() const;
    void drawInstances(const U32 nInstances) const;
  
  
  private:
    void enable() const;
    void disable() const;
    
    void upload_singleBuffer(DeviceBuffer::Usage usage);
    void upload_interleaved(DeviceBuffer::Usage usage);
    void upload_separated(DeviceBuffer::Usage usage);
};

}

#endif // AER_MESH_HPP_


/*******************************************************************

  // HOW TO USE :

  aer::Mesh mesh;

  std::vector<glm::vec3> pos
  std::vector<glm::vec3> nor;
  std::vector<glm::vec2> tex;
  std::vector<unsigned int> indices;
  
  // Create pos, nor, tex.. buffers
  // ..

  mesh.setAttrib( POSITION, (float*)pos.data(), 3, pos.size());
  mesh.setAttrib( NORMAL,   (float*)nor.data(), 3, nor.size());
  mesh.setAttrib( TEXCOORD, (float*)tex.data(), 2, tex.size());
  mesh.setIndices( GL_TRIANGLES, indices.data(), indices.size());

  mesh.upload( DeviceBuffer::STATIC_DRAW, SINGLE_BUFFER);

  //---------
  
  mesh.draw();

********************************************************************/
